<script setup lang="ts">

import {Card, Empty, Modal, Spin, Input} from "ant-design-vue";
import {Page, useVbenModal, VbenButton, Fallback} from '@vben/common-ui';
import { preferences } from '@vben/preferences';
import { VbenIcon } from '@vben/icons';
import {useAccessStore, useUserStore} from "@vben/stores";
import {nextTick, onMounted, ref, useTemplateRef, watch} from "vue";
import {debounce, uniqueId} from 'lodash-es'
import {useEventSource} from "@vueuse/core";
import {useAppConfig} from "@vben/hooks";
import chatNameModel from "./chatNameModel.vue";
import {memoryList} from "#/api/system/ai-chat";
const scrollArea = useTemplateRef('scrollArea');
const userStore = useUserStore();
const avatarUrl = ref('');

avatarUrl.value = userStore.userInfo.avatar || preferences.app.defaultAvatar;

const emptyImage = Empty.PRESENTED_IMAGE_SIMPLE;
const hisloading = ref(false);
const msgloading = ref(false);
const inputMessage = ref('');
const currentHistory = ref<ChatHistory>();
const lastSelectId = ref('');
interface ChatHistory {
  name: string;
  slug: string;
  userId: number;
  active: boolean;
  randomId: string;
}
interface ChatMessage {
  messageType: string;
  content: string;
}
const chatHistory = ref<ChatHistory[]>([{
  name: '默认会话',
  slug: '1',
  userId: 1,
  active: false,
  randomId: '1',
}]);
const chatMessage = ref<ChatMessage[]>([{
  messageType: 'ASSISTANT',
  content: '你好，我是小助手，有什么可以帮助您？',
}]);

// 滚动事件处理（防抖）
const handleMsgScroll = debounce( async (e: Event) => {
  if (msgloading.value) return; // 如果正在加载，直接返回

  // e.target.scrollTop 是元素顶部到当前可视区域顶部的距离，即已滚动的高度。
  // e.target.clientHeight 是元素的可视高度。
  // e.target.scrollHeight 是元素的总高度。
  const { scrollTop, clientHeight, scrollHeight } = e.target as HTMLElement;
  // 判断是否滚动到顶部10px的距离
  const isTop = scrollTop < 10;
  // 只有在接近顶部时触发加载
  if (isTop) {
    await loadMoreData();
  }
}, 200);

const loadMoreData = async () => {

}

const scrollToBottom = () => {
  const container = scrollArea.value;
  if (container) {
    container.scrollTop = container.scrollHeight;
  }
};

const sendMessage = async () => {
  console.log('sendMessage');
  if (!inputMessage.value.trim()  || msgloading.value)  return;
  msgloading.value = true;
  let params = {sessionId: currentHistory.value?.slug, message: inputMessage.value,userId: userStore.userInfo?.userId,mode: "chat",attachments: []}
  // await streamChat(userMsg);
    appendMessage(inputMessage.value, true);
    inputMessage.value = '';
    const { apiURL, clientId, sseEnable } = useAppConfig(
        import.meta.env,
        import.meta.env.PROD,
    );
    const accessStore = useAccessStore();
    const token = accessStore.accessToken;

    const think= ref('');
    const message = ref('');
    appendMessage(message, false);

    const sseAddr = `${apiURL}/system/system/aiChat/streamChat?sessionId=${params.sessionId}&userId=${params.userId}&message=${params.message}&clientid=${clientId}&Authorization=Bearer ${token}`;
    const {data , event, close} = useEventSource(sseAddr,['streamChat'])
    const isthink = ref(false);
    watch(data, async (value) => {
      if (value === '[complete]') {
        msgloading.value = false;
        isthink.value = false;
        close();
        console.log('complete');
      } else {
        message.value += value;
      }
    })
}


async function handleHistoryClick(item: ChatHistory) {
  const { randomId } = item;
  if (lastSelectId.value === randomId) {
    return;
  }
  currentHistory.value = item;
  chatHistory.value.forEach((item) => {
    item.active = item.randomId === randomId;
  });
  lastSelectId.value = randomId;

  const messages = await memoryList();
  console.log(messages);
  // messages.forEach((item) => {
  //   appendMessage(item.content, false)
  // })
  chatMessage.value.push(...messages);
  // chatMessage.value = messages
  await nextTick()
  scrollToBottom()
}
function appendMessage(message, isUser) {
  chatMessage.value.push({
    messageType: isUser ? 'USER' : 'ASSISTANT',
    content: message,
  });
  setTimeout(() => {
    scrollToBottom()
  },50);
}
const [ChatNameModel, modalApi] = useVbenModal({
  connectedComponent: chatNameModel
});
async function startNewChat() {
  console.log('startNewChat')
  modalApi.setData({ userId: userStore.userInfo?.userId });
  modalApi.open();
}
function handleSessionCreated() {
  initialSession();
}
function handleHisDelete(item: ChatHistory) {
  if (chatHistory.value.length <= 1) return;
  console.log('handleHisDelete', item)
  Modal.confirm({
    title: '提示',
    okType: 'danger',
    content: `确认删除选中的记录吗？`,
    onOk: async () => {
      // await delSession(item.slug);
      if (currentHistory.value?.slug === item.slug) {
        initialSession();
      }else{
        initChatHistory();
      }
    },
  });
}
const initChatMessage = async () => {
  console.log('initChatMessage',chatMessage.value);
  if (chatHistory.value.length <= 0) return;
  //默认选择第一个聊天
  handleHistoryClick(chatHistory.value[0]);
}
const initChatHistory = async () => {
  // const sessions = await listSession({userId: userStore.userInfo?.userId});
  // chatHistory.value = sessions.map((item) => {
  //   item.active = false;
  //   item.randomId = uniqueId();
  //   return item;
  // });
  console.log(chatHistory.value)
  chatHistory.value.reverse();
}
const initialSession = async () => {
  console.log('currentHistory ',currentHistory.value)
  await initChatHistory();
  await initChatMessage();
}

onMounted(() => {
  initialSession();
});

</script>

<template>
  <Page :auto-content-height="true">
    <div class="flex h-full gap-2 chat-container">
      <div class="bg-background relative flex h-full min-w-[320px] max-w-[320px] flex-col rounded-lg">
        <div class="bg-background z-100 sticky left-0 top-0 w-full rounded-t-lg border-b-[1px] border-solid p-2">
          <div class="logo-area flex items-center justify-center">
            <span class="logo-text font-bold text-[20px]">Ai Chat</span>
          </div>
          <VbenButton class="w-full" type="primary" @click="startNewChat()">
            <span>新建对话</span>
          </VbenButton>
          <ChatNameModel  @sessionCreated="handleSessionCreated"/>
        </div>
        <div
            ref="cardContainerRef"
            class="thin-scrollbar flex flex-1 flex-col gap-2 overflow-y-auto py-3 cardContainerRef"
            @scroll=""
        >
          <template v-if="chatHistory.length > 0">
            <div
                v-for="item in chatHistory"
                :class="{ 'border-primary': item.active }"
                class="cursor-pointer rounded-lg border-[1px] border-solid p-3 transition-shadow duration-300 ease-in-out hover:shadow-lg"
                @click.stop="handleHistoryClick(item)"
            >
              {{ item.name }}<span v-if="chatHistory.length > 1" @click.stop="handleHisDelete(item)" class="mynaui--trash float-right hover:text-red-500"></span>

            </div>
          </template>
          <Empty v-else :image="emptyImage" />
          <div
              v-if="hisloading"
              class="absolute left-0 top-0 flex h-full w-full items-center justify-center bg-[rgba(0,0,0,0.1)]"
          >
            <Spin tip="加载中..." />
          </div>
        </div>
      </div>
      <Card v-if="currentHistory" :body-style="{ overflowY: 'auto', height: '100%' }" size="small" style="width: 100%">
        <div class="chat-main">
          <div class="chat-container-wrapper">
            <div class="thin-scrollbar flex flex-col gap-2 overflow-y-auto chat-messages" ref="scrollArea" @scroll.passive="handleMsgScroll">
            <div
                v-for="(message, index) in chatMessage"
                :key="index"
                :class="['message', message.messageType === 'USER' ? 'message-user' : 'message-ai']"
            >
              <div class="message-avatar">
                <VbenIcon
                    :icon="message.messageType === 'USER' ? avatarUrl : preferences.app.defaultAvatar
                       "
                    :alt="message.messageType === 'USER' ? '用户' : 'AI'"
                    class="size-10 flex-none rounded-full"
                />
              </div>
              <div class="message-content">
                <div class="message-text" v-html="message.content"></div>
              </div>
            </div>
          </div>

            <div class="chat-input-wrapper flex gap-3">
              <div class="chat-input">
                <div class="input-wrapper">
                  <Input
                    class="send-input"
                    v-model:value="inputMessage"
                    placeholder="请输入您的问题..."
                    resize="none"
                    @keyup.enter.native="sendMessage"
                  />
                  <VbenButton class="send-button" :loading="msgloading" @click.stop="sendMessage">发送</VbenButton>
                </div>
              </div>
            </div>
          </div>
        </div>
      </Card>
      <Fallback v-else title="点击左侧选择" />
    </div>
  </Page>
</template>
<style>
.message-text think{
  display: none;
}
</style>
<style lang="less" scoped>

.cardContainerRef {
  padding-left: 0.75rem;
  padding-right: 0.75rem;
}

.chat-container {
  display: flex;
  background-color: #f5f7fa;
}

.chat-main {
  flex: 1;
  overflow: hidden;
  height: 100%;
  .chat-container-wrapper {
    display: flex;
    flex-direction: column;
    height: 100%;
  }
}

.chat-messages {
  flex: 1;
  padding: 20px;
  overflow-y: auto;
  .message {
    display: flex;
    margin-bottom: 20px;

    &-user {
      flex-direction: row-reverse;

      .message-content {
        margin-right: 12px;

        .message-text {
          background: #e3f2fd;
          border-radius: 12px 2px 12px 12px;
        }
      }
    }

    &-ai .message-content {
      margin-left: 12px;

      .message-text {
        background: #f5f5f5;
        border-radius: 2px 12px 12px 12px;
      }
    }

    &-avatar {
      width: 40px;
      height: 40px;
      border-radius: 50%;
      overflow: hidden;

      img {
        width: 100%;
        height: 100%;
        object-fit: cover;
      }
    }

    &-content {
      max-width: 70%;
    }

    &-text {
      padding: 12px 16px;
      font-size: 14px;
      line-height: 1.5;
    }

    &-time {
      margin-top: 4px;
      font-size: 12px;
      color: #999;
    }
  }
}

.chat-input-wrapper {
  flex-shrink: 0;
  background: #fff;
  border-top: 1px solid #eee;

  .chat-input {
    padding: 20px;
    width: 100%;
    .input-wrapper {
      display: flex;
      gap: 10px;

      .send-input {
        flex: 1;
      }

      .send-button {
        align-self: flex-end;
        width: 100px;
      }
    }
  }
}
.mynaui--trash {
  display: inline-block;
  width: 24px;
  height: 24px;
  --svg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='none' stroke='%23000' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m18 9l-.84 8.398c-.127 1.273-.19 1.909-.48 2.39a2.5 2.5 0 0 1-1.075.973C15.098 21 14.46 21 13.18 21h-2.36c-1.279 0-1.918 0-2.425-.24a2.5 2.5 0 0 1-1.076-.973c-.288-.48-.352-1.116-.48-2.389L6 9m7.5 6.5v-5m-3 5v-5m-6-4h4.615m0 0l.386-2.672c.112-.486.516-.828.98-.828h3.038c.464 0 .867.342.98.828l.386 2.672m-5.77 0h5.77m0 0H19.5'/%3E%3C/svg%3E");
  background-color: currentColor;
  -webkit-mask-image: var(--svg);
  mask-image: var(--svg);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-size: 100% 100%;
  mask-size: 100% 100%;
}

</style>
